package Model;

import java.util.ArrayList;
import java.util.ListIterator;

/**
 * Classe permettant de gérer les dames, elle hérite de la classe Pièce
 * @see Piece
 * @author El Meknassi Hamza (10806466) - Migeon Cyril (11007322)
 */
public class Pion extends Piece{

    public Pion(char couleur, int x, int y, Damier damier)
    {
        super(couleur, x, y, damier);
    }

    
    /**
     * Fonction permettant de vérifier si un déplacement simple (sans prise) est possible ou pas
     * @param caseDepart Case de départ
     * @param caseCible Case cible
     * @param couleurPion Couleur de la dame qu'on essaye de bouger
     * @param joueur On donne le joueur en paramètre pour pouvoir vérifier qu'il a bien le droit de bouger la dame
     * @return <ul><li> Vrai si le déplacement est possible</li><li>Faux sinon</li></ul>
     */
    public boolean verifierDeplacementSimple(Case caseDepart, Case caseCible, char couleurPion, Joueur joueur){
        boolean booleen = true;    
        int xCaseCible = caseCible.getPosition().getX();
        int yCaseCible = caseCible.getPosition().getY();
        int x = caseDepart.getPosition().getX();
        int y = caseDepart.getPosition().getY();

        if(!verifierCouleur(joueur.getCouleur(), this.getCouleur()))
            return false;
        
        if(!verifierEtat(caseCible))
        {
            return false;
        }
        
        if(couleurPion == 'n')
        {
            if((xCaseCible != x+1 && xCaseCible != x-1) || yCaseCible != y+1)
                booleen = false;
        }
        else if(couleurPion == 'b')
        {
            if((xCaseCible != x+1 && xCaseCible != x-1) || yCaseCible != y-1)
                booleen = false;
        }
        
        return booleen;
    }


    /**
     * Fonction de permettant de vérifier si une prise est possible
      * @param caseDepart Case de départ
     * @param caseCible Case sur laquelle on souhaite se déplacer
     * @param couleurPion Couleur du pion que l'on souhaite déplacer
     * @param joueur Joueur effectuant l'opération
     * @return <ul><li>Vrai si la prise est possible</li><li>Faux sinon</li></ul>
     */
    public boolean verifierDeplacementManger(Case caseDepart, Case caseCible, char couleurPion, Joueur joueur){
        boolean booleen = true;    
        int xCaseCible = caseCible.getPosition().getX();
        int yCaseCible = caseCible.getPosition().getY();
        int x = caseDepart.getPosition().getX();
        int y = caseDepart.getPosition().getY();

        if(!verifierEtat(caseCible))
        {
            //System.out.println("Impossible de se déplacer sur cette case");
            return false;
        }

        if(!verifierCouleur(joueur.getCouleur(), this.getCouleur()))
            return false;
        
        if((xCaseCible != x+2 && xCaseCible != x-2) || (yCaseCible != y+2 && yCaseCible != y-2))
        {
            booleen = false;   
        }
        
        if(booleen)
        {
            //On calcule les coordonnées de la case intermédiaire
            int xCaseInter = (x + xCaseCible) / 2;
            int yCaseInter = (y + yCaseCible) / 2;
            //On teste l'etat et la couleur de la case intermédiaire
            if(verifierEtat(this.getDamier().getCase(xCaseInter, yCaseInter)))
                booleen = false;
            else
                if(verifierCouleur(joueur.getCouleur(), this.getDamier().getCase(xCaseInter, yCaseInter).getPiece().getCouleur()))
                    return false;
        }
        return booleen;
    }
    
    /**
     * Fonction permettant de vérifier si le pion peut faire des prises
     * @param pion Pièce que l'on souhaite tester
     * @param pionsJouables Ensemble des pièces pouvant bouger
     * @return <ul><li> Vrai si la pièce est dans la liste</li><li>Faux sinon</li></ul>
     */
    public boolean verifierPionDansPionsJouables(Pion pion, ArrayList<Piece> pionsJouables){
        boolean booleen = false;
        ListIterator<Piece> itr = pionsJouables.listIterator();
        while(itr.hasNext())
        {
            if(pion == itr.next())
            {
                booleen = true;
                break;
            }
        }
        return booleen;        
    }

    /**
     * Fonction permettant de voir si le joueur peut effectuer une prise
     * @param joueur
     * @return <ul><li>Vrai si une prise est possible</li><li>Faux sinon</li></ul>
     */
     public boolean peutManger(Joueur joueur){
         Case[] caseCibles = new Case[4];
         boolean tableauBooleen[] = {true, true, true, true};

         int x = this.getPosition().getX();
         int y = this.getPosition().getY();

         Case caseDepart = this.getDamier().getCase(x, y);

         if(x+2 < 10 && y+2 < 10)
             caseCibles[0] = this.getDamier().getCase(x+2, y+2);
         else tableauBooleen[0]= false;

         if(x-2 > -1 && y+2 < 10)
             caseCibles[1] = this.getDamier().getCase(x-2, y+2);
         else tableauBooleen[1]= false;

         if(x+2 < 10 && y-2 > -1)
             caseCibles[2] = this.getDamier().getCase(x+2, y-2);
         else tableauBooleen[2]= false;

         if(x-2 > -1 && y-2 > -1)
             caseCibles[3] = this.getDamier().getCase(x-2, y-2);
         else tableauBooleen[3]= false;

         for(int i=0; i<4; i++)
         {
             if(caseCibles[i] != null)
             {
                 if(!verifierDeplacementManger(caseDepart, caseCibles[i], this.getCouleur(), joueur))
                     tableauBooleen[i] = false;
             }
         }
         return (tableauBooleen[0] || tableauBooleen[1] || tableauBooleen[2] || tableauBooleen[3]);
     }

     /* Méthode non utilisée pour le moment
     public boolean peutBouger(Joueur joueur){
         Case[] caseCibles = new Case[2];
         boolean tableauBooleen[] = {true, true};
         char couleur = joueur.getCouleur();
         int x = this.getPosition().getX();
         int y = this.getPosition().getY();

         Case caseDepart = this.getDamier().getCase(x, y);

         if (couleur == 'n')
         {
             if(x+1 < 10 && y+1 < 10)
                caseCibles[0] = this.getDamier().getCase(x+1, y+1);
             else tableauBooleen[0]= false;
             if(x-1 > -1 && y+1 < 10)
                caseCibles[1] = this.getDamier().getCase(x-1, y+1);
             else tableauBooleen[1]= false;
         }
         else
         {
             if(x+1 < 10 && y-1 > -1)
                caseCibles[0] = this.getDamier().getCase(x+1, y-1);
             else tableauBooleen[0]= false;
             if(x-1 > -1 && y-1 > -1)
                caseCibles[1] = this.getDamier().getCase(x-1, y-1);
             else tableauBooleen[1]= false;
         }

         for(int i=0; i<2; i++)
         {
             if(caseCibles[i] != null)
             {
                 if(!verifierDeplacementSimple(caseDepart, caseCibles[i],couleur, joueur))
                     tableauBooleen[i] = false;
             }
         }
         return (tableauBooleen[0] || tableauBooleen[1]);
     }*/

    /**
     * Fonction permettant de gérer le déplacement des pions ainsi que les prises et la transformation de pions en dames
     * @param caseDepart Case de départ
     * @param caseCible Case sur laquelle on souhaite se déplacer
     * @param joueur Joueur effectuant l'opération
     * @param pionsJouables Liste des pièces jouables (pouvant faire une prise)
     * @return <ul><li>0 si le déplacement est impossible/li><li>1 si un déplacement ou prise
                      simple est possible</li><li>2 si une prise est encore possible après la prise effectuée</li> </ul>
     */
    public int deplacer(Case caseDepart, Case caseCible, Joueur joueur, ArrayList<Piece> pionsJouables){
        
        int nombrePionsJouables = pionsJouables.size();
        
        if(verifierDeplacementSimple(caseDepart, caseCible, this.getCouleur(), joueur) && nombrePionsJouables == 0)
        {
            if(!verifierPionDansPionsJouables(this, pionsJouables) && nombrePionsJouables != 0)
            {
                System.out.println("Vous avez la possibité d'effetuer une prise avec un autre pion !");
                return 0;
            }
            //Si on arrive ici alors toutes les verifications ont retournées true et on peut procéder au déplacement
            caseDepart.setPiece(null);
            caseDepart.setEtat(0);
            caseCible.setPiece(this);
            caseCible.setEtat(1);
            this.setPosition(caseCible.getPosition());

            //On vérifie que le pion ne devient pas une dame après la prise
            verifierDame(caseCible, joueur);
        }
        else if(verifierDeplacementManger(caseDepart, caseCible, this.getCouleur(), joueur))
        {
            //Si on arrive ici alors toutes les verifications ont retournées true sauf le deplacement simple et on peut procéder au déplacement pour manger un pion adverse
            //On recupère la case où se situe le pion à manger
            //On calcule les coordonnées de la case intermédiaire
            int xCaseInter = (caseDepart.getPosition().getX() + caseCible.getPosition().getX()) / 2;
            int yCaseInter = (caseDepart.getPosition().getY() + caseCible.getPosition().getY()) / 2;
            Case caseInter = this.getDamier().getCase(xCaseInter, yCaseInter);

            caseDepart.setPiece(null);
            caseDepart.setEtat(0);
            caseInter.setPiece(null);
            caseInter.setEtat(0);
            caseCible.setPiece(this);
            caseCible.setEtat(1);
            this.setPosition(caseCible.getPosition());

            //On vérifie si le pion ne devient pas une dame après la prise
            verifierDame(caseCible, joueur);                
            if (verifierNouvellePrise(caseCible, joueur))
                return 2;
        }
        else
        {
            System.out.println("Impossible d'effectuer ce déplacement");
            return 0;
        }
        
        return 1;
    }

    /**
     * Fonction permettant de vérifier si on peut faire une prise multiple après une prise simple
     * @param caseCible Case ou situe la pièce après la prise simple
     * @param joueur Paramètre nécessaire pour la fonction setPiecesJouables que l'on appelle dans cette fonction
     * @return <ul><li>Vrai si une autre prise est possible</li><li>Faux sinon</li></ul>
     */
    private boolean verifierNouvellePrise(Case caseCible, Joueur joueur) {
        this.getDamier().viderCasesProposees();
        this.getDamier().setPiecesJouables(caseCible, joueur);
        if (this.getDamier().getPiecesJouables().isEmpty())
            return false;
        else return true;
    }


    /**
     * Permet de vérifier si le pion devient noir s'il atteint la case cible donnée en paramètre
     * @param caseCible
     * @param joueur
     * @return <ul><li>Vrai si le pion devient une dame</li><li>Faux sinon</li></ul>
     */
    private boolean verifierDame(Case caseCible, Joueur joueur)
    {
        boolean booleen = false;
        if (joueur.getCouleur()== 'b')
        {
            if( caseCible.getPosition().getY() == 0)
            {
                System.out.println("DAME BLANCHE");
                booleen = true;
            }
        }
        else
        {
            if( caseCible.getPosition().getY() == 9)
            {
                System.out.println("DAME NOIRE ");
                booleen=  true;
            }
        }
        if (booleen)
            this.getDamier().creerDame(caseCible.getPosition(),joueur.getCouleur());

        return booleen;
    }

}
